/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.rafkind.crawl.battle;

import com.rafkind.crawl.data.Creature;
import com.rafkind.crawl.data.Team;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

/**
 *
 * @author dave
 */
public class Battle {
  private Random random; 
  
  private Team rightSide;
  private Team leftSide;
  
  private int whoseTurn;
  private Creature[] battleOrder;
  
  private List<BattleListener> listeners;
  
  private boolean first;

  public Battle(Random r, Team leftSide, Team rightSide) {
    random = r;
    this.rightSide = rightSide;
    this.leftSide = leftSide;
    first = true;
    
    listeners = new ArrayList<BattleListener>();
  }  
  
  public void addBattleListener(BattleListener b) {
    listeners.add(b);
  }
  
  public void removeBattleListener(BattleListener b) {
    listeners.remove(b);
  }
  
  private void createNewBattleOrder() {
    
    battleOrder = new Creature[
            rightSide.getMembers().size() 
            + leftSide.getMembers().size()];
    
    int index = 0;
    for (Creature c : rightSide.getMembers()) {
      int baseInitiative = c.getEffectiveInitiative();
      int b23 = 2 * baseInitiative / 3;      
      if (b23 < 1)
	b23 = 1;
      
      c.setCurrentInitiative(random.nextInt(b23) + b23);
      battleOrder[index++] = c;
    }
    
    for (Creature c : leftSide.getMembers()) {
      int baseInitiative = c.getEffectiveInitiative();
      int b23 = 2 * baseInitiative / 3;
      if (b23 < 1)
	b23 = 1;
      
      c.setCurrentInitiative(random.nextInt(b23) + b23);
      battleOrder[index++] = c;
    }
    
    Arrays.sort(battleOrder, new Comparator<Creature>(){
      public int compare(Creature a, Creature b) {
        return b.getCurrentInitiative() - a.getCurrentInitiative();
      }      
    });
    
    whoseTurn = 0;
  }
  
  public BattleResult advance() {    
    BattleResult answer = BattleResult.CONTINUE;
    
    if (first) {
      for (BattleListener b : listeners)
        b.battleStart(this);
      first = false;
    }
    
    if (battleOrder == null || whoseTurn >= battleOrder.length) {
      createNewBattleOrder();
      for (BattleListener b : listeners)
        b.roundStart(this);
    }
    
    Creature actor = battleOrder[whoseTurn++];    
    if (actor.isActiveInBattle()) {
      for (BattleListener b : listeners) 
	b.beforeActorDecision(this, actor);
      BattleCommand command = actor.getBattleCommand();        
      for (BattleListener b : listeners) 
	b.afterActorDecision(this, actor);
      for (BattleListener b : listeners) 
	b.beforeActorAction(this, actor);
      answer = command.execute(listeners);   
      for (BattleListener b : listeners) 
	b.afterActorDecision(this, actor);    
    }
    
    return answer.merge(checkVictory());
  }
  
  private BattleResult checkVictory() {
    if (!leftSide.hasAnyActiveMembers() || !rightSide.hasAnyActiveMembers())
      return BattleResult.VICTORY_OR_DEFEAT;
    
    return BattleResult.CONTINUE;
  }
}